<?php
/**
 * Nweb Framework
 *
 * This script is protected by copyright. It's use, copying, modification
 * and distribution without written consent of the author is prohibited.
 *
 * @category    source
 * @package     pl.nweb.framework.request
 * @subpackage  pl.nweb.framework.request.http
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt  GNU Lesser General Public
 * @version     3.0 $Id$
 * @link        http://code.google.com/p/nweb-framework/
 * @link        http://framework.nweb.pl
 */

namespace pl\nweb\framework\request;

/**
 * Żądanie HTTP
 *
 * @category    source
 * @package     pl.nweb.framework.request
 * @subpackage  pl.nweb.framework.request.http
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @version     3.0 $Id$
 */
class Http extends \pl\nweb\framework\Request
{
    /**
     * Parametry żądania
     *
     * @var array
     */
    private $_apache_headers = array();

    /**
     * Nazwa hosta
     *
     * @var string
     */
    private $_host = null;

    /**
     * Schemat
     *
     * @var string
     */
    private $_scheme = null;

    /**
     * Bazowy adres url
     * np. http://host.com/site
     *
     * @var string
     */
    private $_baseUrl = null;

    /**
     * Scieżka bazowa
     * np. /site
     *
     * @var string
     */
    private $_basePath = null;

    /**
     * URI żądania
     *
     * @var string
     */
    private $_requestUri = null;

    /**
     * Scieżka wywołania
     * np. /module/controller/action
     *
     * @var string
     */
    private $_pathInfo = null;


    /**
     * Konstruktor
     *
     * @param array $params parametry
     */
    public function __construct (array $params = array())
    {
        parent::__construct($params);
        if (function_exists('apache_request_headers')) {
            $this->_apache_headers = apache_request_headers();
        }
    }

    /**
     * Zwraca wartość parametru
     *
     * @param string $name nazwa parametru
     * @return mixed
     */
    public function getParam ($name = null, $default = null)
    {
        if (isset($this->_params[$name])) {
            return $this->_params[$name];
        } elseif (isset($_GET[$name])) {
            return $_GET[$name];
        } elseif (isset($_POST[$name])) {
            return $_POST[$name];
        } else {
            return $default;
        }
    }

    /**
     * Zwraca ścieżkę bazową
     *
     * @return string|null
     */
    public function getBasePath ()
    {
        /**
               [QUERY_STRING] => route=fasja
               [REQUEST_URI]  => /workspace/test/http/index.php/siema/?route=fasja
			   [SCRIPT_NAME]  => /workspace/test/http/index.php
			   [PHP_SELF]     => /workspace/test/http/index.php/siema/

			   [REQUEST_URI] => /workspace/test/http/siema/?route=fasja
			   [PHP_SELF]    => /workspace/test/http/index.php
			   [SCRIPT_NAME] => /workspace/test/http/index.php

			   [REQUEST_URI] => /siema/?route=fasja
			   [SCRIPT_NAME] => /index.php


			   [REQUEST_URI] => /index.php/siema/?route=fasja
			   [SCRIPT_NAME] => /index.php


			   [REQUEST_URI] => /
			   [SCRIPT_NAME] => /index.php

			   [REQUEST_URI] => /index.php
			   [SCRIPT_NAME] => /index.php


			   [SCRIPT_FILENAME] => /var/www/index.php
   			   [PHP_SELF] => /index.php

         */

        if ($this->_basePath === null) {
            $script_name = '';
            if(isset($_SERVER['SCRIPT_NAME'])) {
                $script_name = $_SERVER['SCRIPT_NAME'];
            } else if (isset($_SERVER['ORIG_SCRIPT_NAME'])) {
                $script_name = $_SERVER['ORIG_SCRIPT_NAME'];
            } else if (isset($_SERVER['SCRIPT_FILENAME'], $_SERVER['PHP_SELF'])) {
                $filename = substr($_SERVER['SCRIPT_FILENAME'], strrpos($_SERVER['SCRIPT_FILENAME'], '/'));
                $script_name = substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], $filename) + strlen($filename));
            } else {
                throw new Exception ('Cannot resolve url base path');
            }

            $requestUri = $this->getRequestUri();
            $len = strlen($script_name);
            if(strncmp($script_name, $requestUri, $len) == 0) {
                $this->_basePath = $script_name . '/';
            } else {
                $this->_basePath = substr($script_name, 0, strrpos($script_name, '/')) . '/';
            }
        }
        return $this->_basePath;
    }

    /**
     * Zwraca bazowy adres url
     *
     * @return string|null
     */
    public function getBaseUrl ()
    {
        if ($this->_baseUrl === null) {
            $this->_baseUrl = $this->getScheme() . '://' . $this->getHttpHost() . $this->getBasePath();
        }
        return $this->_baseUrl;
    }

    /**
     * Zwraca ścieżkę wywołania aplikacji
     *
     * @return string|null
     */
    public function getPathInfo ()
    {
        if ($this->_pathInfo === null) {
            $requestUri = $this->getRequestUri();
            if(isset($_SERVER['PATH_INFO'])) {
                $this->_pathInfo = $_SERVER['PATH_INFO'];
            } else {
                $bsp = $this->getBasePath();
                $path = substr($requestUri, strlen($bsp));
                if(($pos = strpos($path, '?')) !== false) {
                    $path = substr($path, 0, $pos);
                }
                $this->_pathInfo = $path;
            }
        }
        return $this->_pathInfo;
    }

    /**
     * Zwraca REQUEST_URI
     *
     * @return string
     */
    public function getRequestUri ()
    {
       if (null === $this->_requestUri) {
       	    $requestUri = '';
            if (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
                $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
            } elseif (isset($_SERVER['REQUEST_URI'])) {
                $requestUri = $_SERVER['REQUEST_URI'];
            } elseif (isset($_SERVER['ORIG_PATH_INFO'])) {
                $requestUri = $_SERVER['ORIG_PATH_INFO'];
                if (!empty($_SERVER['QUERY_STRING'])) {
                    $requestUri .= '?' . $_SERVER['QUERY_STRING'];
                }
            }
            $this->_requestUri = $requestUri;
       }
       return $this->_requestUri;
    }


    /**
     * Zwraca wartość ze zmiennej globalnej $_GET,
     * w przypadku braku podania klucza zwraca całą tablicę $_GET
     *
     * @param string $key klucz
     * @param mixed $default domyślna wartość w przypadku braku w tablicy
     * @return mixed
     */
    public function getQuery ($key = null, $default = null)
    {
        if (null === $key) {
            return $_GET;
        }
        return (isset($_GET[$key])) ? $_GET[$key] : $default;
    }

    /**
     * Zwraca wartość ze zmiennej globalnej $_POST,
     * w przypadku braku podania klucza zwraca całą tablicę $_POST
     *
     * @param string $key klucz
     * @param mixed $default domyślna wartość w przypadku braku w tablicy
     * @return mixed
     */
    public function getPost ($key = null, $default = null)
    {
        if (null === $key) {
            return $_POST;
        }
        return (isset($_POST[$key])) ? $_POST[$key] : $default;
    }

    /**
     * Zwraca wartość ze zmiennej globalnej $_COOKIE,
     * w przypadku braku podania klucza zwraca całą tablicę $_COOKIE
     *
     * @param string $key klucz
     * @param mixed $default domyślna wartość w przypadku braku w tablicy
     * @return mixed
     */
    public function getCookie ($key = null, $default = null)
    {
        if (null === $key) {
            return $_COOKIE;
        }
        return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default;
    }

    /**
     * Zwraca wartość ze zmiennej globalnej $_SERVER,
     * w przypadku braku podania klucza zwraca całą tablicę $_SERVER
     *
     * @param string $key klucz
     * @param mixed $default domyślna wartość w przypadku braku w tablicy
     * @return mixed
     */
    public function getServer ($key = null, $default = null)
    {
        if (null === $key) {
            return $_SERVER;
        }

        return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default;
    }

    /**
     * Zwraca wartość ze zmiennej globalnej $_ENV,
     * w przypadku braku podania klucza zwraca całą tablicę $_ENV
     *
     * @param string $key klucz
     * @param mixed $default domyślna wartość w przypadku braku w tablicy
     * @return mixed
     */
    public function getEnv ($key = null, $default = null)
    {
        if (null === $key) {
            return $_ENV;
        }

        return (isset($_ENV[$key])) ? $_ENV[$key] : $default;
    }

    /**
     * Zwraca metodę żądania
     *
     * @return string
     */
    public function getMethod ()
    {
        return $this->getServer('REQUEST_METHOD');
    }

    /**
     * Zwraca flagę czy metoda żądania to POST
     *
     * @return boolean
     */
    public function isPost ()
    {
        return ('POST' == $this->getMethod());
    }

    /**
     * Zwraca flagę czy metoda żądania to GET
     *
     * @return boolean
     */
    public function isGet ()
    {
        return ('GET' == $this->getMethod());
    }

    /**
     * Zwraca flagę czy metoda żądania to PUT
     *
     * @return boolean
     */
    public function isPut ()
    {
        return ('PUT' == $this->getMethod());
    }

    /**
     * Zwraca flagę czy metoda żądania to DELETE
     *
     * @return boolean
     */
    public function isDelete ()
    {
        return ('DELETE' == $this->getMethod());
    }

    /**
     * Zwraca flagę czy metoda żądania to HEAD
     *
     * @return boolean
     */
    public function isHead ()
    {
        return ('HEAD' == $this->getMethod());
    }

    /**
     * Zwraca flagę czy metoda żądania to OPTIONS
     *
     * @return boolean
     */
    public function isOptions ()
    {
        return ('OPTIONS' == $this->getMethod());
    }

    /**
     * Zwraca nagłówek HTTP
     *
     * @param string $header nazwa nagłówka HTTP
     * @return string|false
     */
    public function getHeader ($header)
    {
        $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
        if (!empty($_SERVER[$temp])) {
            return $_SERVER[$temp];
        }

        if (!empty($this->_apache_headers[$header])) {
            return $this->_apache_headers[$header];
        }

        return false;
    }

    /**
     * Zwraca flagę czy żądanie wywołane jest przez Java Script (AJAX)
     *
     * @return boolean
     */
    public function isXmlHttpRequest ()
    {
        return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }

    /**
     * Zwraca flagę czy żadanie wywołane jest przez Flash
     *
     * @return bool
     */
    public function isFlashRequest ()
    {
        $header = strtolower($this->getHeader('USER_AGENT'));
        return (strstr($header, ' flash')) ? true : false;
    }

    /**
     * Zwraca protokół (schemat) URI
     *
     * @return string
     */
    public function getScheme()
    {
        if(null == $this->_scheme) {
            $this->_scheme = ($this->getServer('HTTPS') == 'on') ? 'https' : 'http';
        }
        return $this->_scheme;
    }

    /**
     * Zwraca nazwę hosta
     *
     * @return string
     */
    public function getHost()
    {
        if(null === $this->_host) {
            $this->_host = $this->getServer('HTTP_HOST');
            if ($this->_host = $this->getServer('HTTP_HOST')) {
                return $this->_host;
            }

            $scheme = $this->getScheme();
            $name   = $this->getServer('SERVER_NAME');
            $port   = $this->getServer('SERVER_PORT');

            if (($scheme == 'http' && $port == 80) || ($scheme == 'https' && $port == 443)) {
                $this->_host = $name;
            } else {
                $this->_host = $name . ':' . $port;
            }
        }
        return $this->_host;
    }
}